package br.ufrj.dcc.tp.servidor.log;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

import br.ufrj.dcc.tp.servidor.interfaces.ILogStream;

public class Log {
	private static ArrayList<ILogStream> logs;
	private static SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss", Locale.getDefault());
	static {
		logs = new ArrayList<ILogStream>();
	}
	
	public static void addLogStream(ILogStream log) {
		logs.add(log);
	}
	
	/**
	 * Escreve uma mensagem de severidade LogLevel.INFO 
	 * 
	 * @param klass A classe que lancou a mensagem de log.
	 * @param obj O objeto que tera seu metodo toString() logado.
	 */
	public static void write(Class<?> klass, Object obj) {
		log(klass, LogLevel.INFO, obj);
	}
	
	private static void log(Class<?> klass, LogLevel level, Object obj) {
		StringBuffer sb = new StringBuffer();
		
		sb.append(sdf.format(new Date()))
			.append(" [").append(klass.getSimpleName()).append("] ")
			.append(level.getNome())
			.append(" - ")
			.append(obj.toString())
			.append("\n");
		
		try {
			for( ILogStream log : logs ) {
				log.log(sb.toString());
				log.flushLog();
			}
		} catch (Exception e) {
			System.out.println(obj);
			e.printStackTrace();
		}
	}
	
	/**
	 * Escreve uma mensagem de log. 
	 * 
	 * @param klass A classe que lancou a mensagem de log.
	 * @param level A severidade da mensagem de log.
	 * @param obj O objeto que tera seu metodo toString() logado.
	 */
	public static void write(Class<?> klass, LogLevel level, Object obj) {
		log(klass, level, obj);
	}
	
	/**
	 * Escreve o stackTrace de uma excecao. 
	 * 
	 * @param klass A classe que lancou a mensagem de log.
	 * @param e A excecao que foi lancada.
	 */
	public static void write(Class<?> klass, Exception e) {
		StringBuffer sb = new StringBuffer();
		sb.append(e.getClass().toString()).append(" ").append(e.getMessage());
		
		for( StackTraceElement ste : e.getStackTrace() ) {
			sb.append("\n\t")
				.append(ste.getFileName()).append(":")
				.append(ste.getLineNumber())
				.append(" ")
				.append(ste.getClassName())
				.append(".")
				.append(ste.getMethodName());
		}
		
		sb.append("\n(").append(klass.getName()).append(")\n");
		
		try {
			for( ILogStream log : logs ) {
				log.log(sb.toString());
				log.flushLog();
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}
